#include "memory.h"
#include "options.h"
#include "strategy.h"

CMemory::CMemory(IMemoryStrategy* strategy)
:strategy_(strategy)
{

}

CMemory::~CMemory()
{
	block_lock.Lock();
	block* pBlock = block_pool.get();
	while(pBlock)
	{
			strategy_->force_free_block(pBlock);
			pBlock = block_pool.get();
	}	
	block_lock.UnLock();
	
	msg_lock.Lock();
	msg* pMsg = msg_pool.get();
	while(pMsg)
	{
		strategy_->force_free_msg(pMsg);
		pMsg = msg_pool.get();
	}
	msg_lock.UnLock();

	delete strategy_;
	strategy_ = 0;
}

struct block* CMemory::alloc_block()
{
	block* ret = 0;
	block_lock.Lock();
	ret = block_pool.get();
	if(0==ret)
		ret = strategy_->alloc_block();
	block_lock.UnLock();

	assert(ret);
	ret->next = 0;
	ret->refcount = 1;

	return ret;
}

void 
CMemory::free_block(struct block* ptr_block)
{
	if(ptr_block&&ptr_block->release())
	{
		block_lock.Lock();
		strategy_->free_block(ptr_block);
		if(0!=ptr_block)
			block_pool.add_head(ptr_block);
		block_lock.UnLock();
	}
}

struct msg* CMemory::alloc_msg()
{
	msg* ret = 0;
	msg_lock.Lock();
	ret = msg_pool.get();
	if(0==ret)
		ret = strategy_->alloc_msg();
	msg_lock.UnLock();

	assert(ret);
	ret->next = 0;
	ret->readpos = 0;
	ret->writepos = 0;
	ret->data = 0;
	ret->totalsize = 0;	
	return ret;
}

void CMemory::free_msg(struct msg* ptr_msg)
{
	if(!ptr_msg) return;

	if(ptr_msg->data)
		free_block(ptr_msg->data);
	ptr_msg->data = 0;

	msg_lock.Lock();
	strategy_->free_msg(ptr_msg);
	if(ptr_msg)
		msg_pool.add_head(ptr_msg);
	msg_lock.UnLock();
}

int CMemory::get_block_count()
{
	return block_pool.count;
}

int CMemory::get_msg_count()
{
	return msg_pool.count;
}